#include "gd32f4xx.h"
#include "sys_type.h"
#include "bsp_io.h"
#include "bsp_wdg.h"
#include "bsp_can.h"

can_trasnmit_message_struct st_can_transmit_message;
can_receive_message_struct st_can_receive_message;

void vCAN_Init(uint16_t baud)
{
	can_parameter_struct			can_parameter;
	can_filter_parameter_struct 	can_filter;
	
    /* enable CAN clock */
    rcu_periph_clock_enable(RCU_CAN0);
    rcu_periph_clock_enable(RCU_GPIOB);
    
    /* configure CAN0 GPIO */
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_8);
    
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_9);


	can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
	can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);
	/* initialize CAN register */
	can_deinit(CAN0);
	
	/* initialize CAN parameters */
	can_parameter.time_triggered = DISABLE;
	can_parameter.auto_bus_off_recovery = ENABLE;
	can_parameter.auto_wake_up = DISABLE;
	can_parameter.auto_retrans = ENABLE;
	can_parameter.rec_fifo_overwrite = DISABLE;
	can_parameter.trans_fifo_order = DISABLE;
	can_parameter.working_mode = CAN_NORMAL_MODE;
	can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
	can_parameter.time_segment_1 = CAN_BT_BS1_13TQ;
	can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
	can_parameter.prescaler = baud;
		
	/* initialize CAN */
	can_init(CAN0, &can_parameter);

	/* initialize filter */ 
	can_filter.filter_number=0;
	can_filter.filter_mode = CAN_FILTERMODE_MASK;
	can_filter.filter_bits = CAN_FILTERBITS_32BIT;
	can_filter.filter_list_high = 0x0000;
	can_filter.filter_list_low = 0x0000;
	can_filter.filter_mask_high = 0x0000;
	can_filter.filter_mask_low = 0x0000;
	can_filter.filter_fifo_number = CAN_FIFO1;
	can_filter.filter_enable = ENABLE;
	can_filter_init(&can_filter);

	nvic_irq_enable(CAN0_RX1_IRQn,0,0);
	can_interrupt_enable(CAN0, CAN_INT_RFNE1);
}


void vCanSendData(can_trasnmit_message_struct* msg)
{
	USHORT wk_timeout = 0xFFFF;
	UCHAR transmit_mailbox;
	
	transmit_mailbox = can_message_transmit(CAN0, msg);
	/* waiting for transmit completed */
	while((CAN_TRANSMIT_OK != can_transmit_states(CAN0, transmit_mailbox)) && (0 != wk_timeout))
	{
		wk_timeout--;
	}
}

void CAN_RxCallBack(void)
{
    can_message_receive(CAN0, CAN_FIFO1, &st_can_receive_message);
}

